﻿using System;
using System.Collections.Generic;
using Home.Haushalt.Lib;
using Home.Haushalt.Lib.Element;
using Infragistics.Win.UltraWinGrid;
using System.Windows.Forms;
using System.Data;
using Infragistics.Win;
using System.IO;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;

namespace Home.Haushalt.Gui
{
    /// <summary>
    /// 
    /// </summary>
    public partial class FrmPropertyDocument : FrmProperty
    {
        /// <summary></summary>
        private OpenFileDialog _openFileDialog = new OpenFileDialog();

        /// <summary></summary>
        private DataTable _pageTempTable;

        /// <summary></summary>
        private Document _document { get { return (Document)_elementObject; } }

        /// <summary>
        /// 
        /// </summary>
        public FrmPropertyDocument()
        {
            InitializeComponent();

            _openFileDialog.Multiselect = true;

        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmPropertyDocument_Load(object sender, EventArgs e)
        {
            _document.OnAcceptChanges += new EventHandler<HEventArgs>(_elementObject_OnAcceptChanges);
            _document.OnRejectChanges += new EventHandler<HEventArgs>(ElementObject_OnRejectChanges);

            //Hauptelement
            lstDocutype.AddBinding(_elementObject, Document.Fields.DocuTypeId);
            lstWay.AddBinding(_elementObject, Document.Fields.WayId);
            lstDirection.AddBinding(_elementObject, Document.Fields.DirectionId);
            lstOpponent.AddBinding(_elementObject, Document.Fields.OpponentId);
            lstPosten1.AddBinding(_elementObject, Document.Fields.PostenId);
            lstPosten2.AddBinding(_elementObject, Document.Fields.PostenExt1Id);
            lstPosten3.AddBinding(_elementObject, Document.Fields.PostenExt2Id);
            lstPosten4.AddBinding(_elementObject, Document.Fields.PostenExt3Id);

            AddBinding(calFrom.DataBindings, "Value", Document.Fields.Date);

            AddBinding(cbCrypted.DataBindings, "Checked", Document.Fields.Crypted);
            _document.InitialCrypted = _document.BindingRow[Document.Fields.Crypted].ToBool(false);

            DataBind();

            //Die in MultiSelection-Mode nicht erlaubten Felder sperren
            if (!SingleSelection)
            {
                lstDocutype.Enabled = false;
                lstWay.Enabled = false;
                lstDirection.Enabled = false;
                lstOpponent.Enabled = false;
                cbCrypted.Enabled = false;
                calFrom.Enabled = false;
                gridPage.Enabled = false;
                btnStartScreenCuter.Enabled = false;
            }

            //Pages
            gridPage.DragEnter += new System.Windows.Forms.DragEventHandler(gridPage_DragEnter);
            gridPage.DragDrop += new DragEventHandler(gridPage_DragDrop);
            gridPage.ContextMenuStrip.Opened += new EventHandler(ContextMenuStrip_Opened);

            BindGridPage();

            SetAppState();
        }

        #region PAGE GRID

        /// <summary>
        /// 
        /// </summary>
        private void BindGridPage()
        {
            _pageTempTable = DAO.Tables[Page.ElementType].Clone();
            foreach (DataRow row in DAO.GetSubRows(Page.ElementType, Page.Fields.DocumentId, _elementObject.ID))
            {
                _pageTempTable.ImportRow(row);

                DataRow pageRow = _pageTempTable.Rows[_pageTempTable.Rows.Count - 1];

                pageRow[Page.Fields.SourceFileName] = new Page(pageRow).CreateFileStoreName(_document.Row);
            }

            Page pageObj = (Page)ElementBase.Instantiate(Page.ElementType);
            pageObj.SetElementTable(_pageTempTable);

            gridPage.DataBind(pageObj, DefaultColumnSets.GridDefault);

            _document.PageChanged = false;

            gridPage.LoadLayout(DefaultColumnSets.GridDefault.ToString());
            gridPage.DisplayLayout.Override.AllowRowFiltering = DefaultableBoolean.False;
            gridPage.DisplayLayout.Override.HeaderClickAction = HeaderClickAction.Select;
            gridPage.DisplayLayout.GroupByBox.Hidden = true;

            gridPage.DisplayLayout.Bands[0].SortedColumns.Add(Page.Fields.Index, false);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="files"></param>
        public void AddPages(params string[] files)
        {
            //Grösstes Index finden
            int index = 0;
            DataRow[] rows = _pageTempTable.Select(string.Format("{0} = {1}", Page.Fields.DocumentId, _elementObject.ID), Page.Fields.Index + " desc");
            if (rows.Length > 0)
            {
                index = rows[0][Page.Fields.Index].ToInt();
            }

            //Seite hinzufügen
            foreach (string filename in files)
            {
                //Prüfen ob die Datei bereits hinzugefügt ist
                if (_pageTempTable.Select(string.Format("{0} = {1} and {2} = '{3}'", Page.Fields.DocumentId, _elementObject.ID, Page.Fields.SourceFileName, filename)).Length == 0)
                {
                    //Datei-Typ bestimmen
                    string ext = Path.GetExtension(filename);
                    int typeId = 0;
                    DataRow[] fileTypeRows = DAO.Tables[FileType.ElementType].Select(string.Format("{0} = '{1}'", FileType.Fields.Ext, ext));
                    if (fileTypeRows.Length > 0)
                    {
                        typeId = fileTypeRows[0][FileType.Fields.Id].ToInt();
                    }

                    //Neue Datei hinzufügen
                    DataRow row = _pageTempTable.NewRow();
                    row[Page.Fields.DocumentId] = _elementObject.ID;
                    row[Page.Fields.TypeId] = typeId;
                    row[Page.Fields.Index] = ++index;
                    row[Page.Fields.SourceFileName] = filename;

                    _pageTempTable.Rows.Add(row);
                }
            }

            gridPage.InitializeRowsAppearances();

            _document.PageChanged = true;

            SetAppState();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ContextMenuStrip_Opened(object sender, EventArgs e)
        {
            if (gridPage._clickedObject is UltraGridCell || gridPage._clickedObject is UltraGrid)
            {
                gridPage.ContextMenuStrip.Items.Clear();

                int insertIndex = 0;

                string elementCaption = (gridPage.Selected.Rows.Count > 1) ? LO.ElementList(Page.ElementType) : LO.ElementName(Page.ElementType);

                ToolStripMenuItem openElementItem = new ToolStripMenuItem(LO.GridContextMenu("Element.Open", elementCaption) + " [Enter]", null, cmnuPropertyOpen_Click);
                gridPage.ContextMenuStrip.Items.Insert(insertIndex++, openElementItem);

                ToolStripMenuItem toClipboardElementItem = new ToolStripMenuItem(LO.GridContextMenu("Element.ToClipboard", elementCaption) + " [Strg+C]", null, cmnuCopyToClipboard_Click);
                toClipboardElementItem.Enabled = (gridPage.Selected.Rows.Count > 0);
                gridPage.ContextMenuStrip.Items.Insert(insertIndex++, toClipboardElementItem);

                gridPage.ContextMenuStrip.Items.Insert(insertIndex++, new ToolStripSeparator());

                ToolStripMenuItem contextMenuNewElementItem = new ToolStripMenuItem(LO.GridContextMenu("Element.Create", elementCaption) + " [Strg+V]", global:: Home.Haushalt.Lib.Properties.Resources.element_new, cmnuPropertyNew_Click);
                gridPage.ContextMenuStrip.Items.Add(contextMenuNewElementItem);

                ToolStripMenuItem contextMenuDeleteElementItem = new ToolStripMenuItem(LO.GridContextMenu("Element.Delete", elementCaption)+" [Del]", global:: Home.Haushalt.Lib.Properties.Resources.element_delete, cmnuPropertyDelete_Click);
                contextMenuDeleteElementItem.Enabled = (gridPage.Selected.Rows.Count > 0);
                gridPage.ContextMenuStrip.Items.Add(contextMenuDeleteElementItem);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmnuPropertyNew_Click(object sender, EventArgs e)
        {
            if (_openFileDialog.ShowDialog().Equals(DialogResult.OK))
            {
                AddPages(_openFileDialog.FileNames);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridPage_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Modifiers == Keys.Control)
            {
                switch (e.KeyCode)
                {
                    case Keys.C:
                        cmnuCopyToClipboard_Click(null, null);
                        break;

                    case Keys.V:
                        if (Clipboard.ContainsImage())
                        {
                            AddPages(DAO.HFile.CreateImageFromClipboard());
                        }
                        break;
                }
            }
            else if (e.KeyCode.Equals(Keys.Delete))
            {
                cmnuPropertyDelete_Click(sender, e);
            }
            else if (e.KeyCode.Equals(Keys.Enter))
            {
                cmnuPropertyOpen_Click(sender, e);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmnuPropertyDelete_Click(object sender, EventArgs e)
        {
            while (gridPage.Selected.Rows.Count > 0)
            {
                gridPage.Selected.Rows[0].ToDataRow().Delete();
            }

            int index = 1;
            foreach (DataRow row in _pageTempTable.Select(string.Format("{0} = {1}", Page.Fields.DocumentId, _elementObject.ID), Page.Fields.Index + " asc"))
            {
                row[Page.Fields.Index] = index++;
            }

            _document.PageChanged = true;
            SetAppState();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmnuCopyToClipboard_Click(object sender, EventArgs e)
        {
            Clipboard.Clear();

            StringCollection paths = new StringCollection();
            foreach (UltraGridRow row in gridPage.Selected.Rows)
            {
                paths.Add(new Page(row.ToDataRow()).DecryptFilePath);
            }

            Clipboard.SetFileDropList(paths);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridPage_DoubleClickRow(object sender, DoubleClickRowEventArgs e)
        {
            cmnuPropertyOpen_Click(sender, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmnuPropertyOpen_Click(object sender, EventArgs e)
        {
            foreach (UltraGridRow row in gridPage.Selected.Rows)
            {
                Page pageObj = new Page(row.ToDataRow());

                string filename = "";

                if (pageObj.Row[Page.Fields.SourceFileName] != null &&
                    pageObj.Row[Page.Fields.SourceFileName].ToString().Length > 0 &&
                    File.Exists(pageObj.Row[Page.Fields.SourceFileName].ToString()))
                {
                    filename = row.ToDataRow()[Page.Fields.SourceFileName].ToString();
                }
                else
                {
                    filename = pageObj.DecryptFilePath;
                }

                try
                {
                    Process.Start(filename);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Datei kann nicht geöffnet werden: " + ex.Message);
                    Journal.Add(this, ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridPage_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.Bitmap) || e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridPage_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                AddPages((string[])e.Data.GetData(DataFormats.FileDrop));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridPage_BeforeRowsDeleted(object sender, BeforeRowsDeletedEventArgs e)
        {
            e.DisplayPromptMsg = false;
        }

        #endregion PAGE GRID

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ElementObject_OnRejectChanges(object sender, HEventArgs e)
        {
            BindGridPage();

            SetAppState();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _elementObject_OnAcceptChanges(object sender, HEventArgs e)
        {
            Document document = (Document)sender;
            DataRow oldDocuRow = (DataRow)e.Tag;

            //Dateien umbenennen nur wenn es nötig ist (wenigstens eine Datei-Namen relevante Eigenschaft hat sich geändert)
            if (document.PageChanged)
            {
                //Bestehende Dateien löschen oder in Temp umbenennen
                List<DataRow> toDelete = new List<DataRow>();
                foreach (DataRow row in DAO.GetSubRows(Page.ElementType, Page.Fields.DocumentId, document.ID))
                {
                    Page pageObj = new Page(row);

                    if (_pageTempTable.Select(string.Format("{0} = {1}", Page.Fields.Id, row[Page.Fields.Id])).Length > 0)
                    {
                        string currentFilePath = Path.Combine(DAO.HFile.FileStoreFullPath, pageObj.CreateFileStoreName(oldDocuRow));
                        pageObj.Row[Page.Fields.SourceFileName] = currentFilePath + ".temp";

                        File.Move(currentFilePath, pageObj.Row[Page.Fields.SourceFileName].ToString());
                    }
                    else
                    {
                        //Fürs Löschen markieren
                        toDelete.Add(row);
                    }
                }

                //Dateien löschen
                while (toDelete.Count > 0)
                {
                    Page pageObj = new Page(toDelete[0]);
                    string filePath = Path.Combine(DAO.HFile.FileStoreFullPath, pageObj.CreateFileStoreName(oldDocuRow));

                    //Aus dem DB löschen
                    toDelete[0].Delete();

                    //Datei löschen
                    DAO.HFile.Delete(filePath);

                    toDelete.RemoveAt(0);
                }

                //Dateien kopieren und umbenennen
                foreach (DataRow changedRow in _pageTempTable.Rows)
                {
                    changedRow[Page.Fields.DocumentId] = document.ID;
                    Page changedPageObj = new Page(changedRow);

                    if (changedPageObj.ID > 0)
                    {
                        //Bestehende Datei
                        DataRow originalRow = DAO.GetSubRows(Page.ElementType, Page.Fields.Id, changedPageObj.ID)[0];
                        Page originalPageObj = new Page(originalRow);

                        File.Move(originalPageObj.Row[Page.Fields.SourceFileName].ToString(), changedPageObj.FilePath);

                        originalRow.Delete();
                    }
                    else
                    {
                        //Neue Datei
                        changedPageObj.SetNextId();

                        try
                        {
                            File.Copy(changedPageObj.Row[Page.Fields.SourceFileName].ToString(), changedPageObj.FilePath, true);

                            //Mit dem für bestehende Datei Crypt-Eigenschaft behandeln
                            //(wenn alte nicht crypted muss der neue auch nicht crypted sein, obwohl neue crypt Eigenschaft true ist)
                            if (document.InitialCrypted)
                            {
                                DAO.Credential.CurrentCry.FileEncrypt(changedPageObj.FilePath);
                            }
                        }
                        catch (Exception ex)
                        {
                            Journal.Add(this, ex);
                        }
                    }

                    changedPageObj.Row[Page.Fields.SourceFileName] = null;

                    DAO.Tables[Page.ElementType].ImportRow(changedRow);

                    //changedPageObj.SaveToChangeBackup();
                    changedPageObj.MarkAsChanged();
                }

                //Wenn Crypt-Eigenschaft verändert - für alle Dateien ändern
                if (!document.InitialCrypted.Equals(document.Row[Document.Fields.Crypted].ToBool(false)))
                {
                    document.Crypt(document.Row[Document.Fields.Crypted].ToBool(false));
                }
            }

            BindGridPage();

            gridPage.InitializeRowsAppearances();
            WindowController.RefreshGrids(Page.ElementType);

            SetAppState();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStartScreenCuter_Click(object sender, EventArgs e)
        {
            if (!System.Diagnostics.Process.GetProcesses().Any(item => item.ProcessName.Equals("ScreenCaptureUltra")))
            {
                Process.Start("ScreenCaptureUltra.exe");
            }
        }






    }
}
